#include "GameControl.h"
#include "PlayHand.h"
#include <QRandomGenerator>
#include <QTimer>

GameControl::GameControl(QObject *parent)
    : QObject{parent}
{}

void GameControl::playerInit()
{
    m_user = new UserPlayer("黄彪彪",this);
    m_robotLeft = new Robot("机器人A",this);
    m_robotRight = new Robot("机器人B",this);

    //属性初始化（目前只需要初始化头像显示位置，性别,出牌顺序）
    m_robotLeft->setDirection(Player::Direction::Left);
    m_robotRight->setDirection(Player::Direction::Right);
    m_user->setDirection(Player::Direction::Right);

    Player::Sex sex;//性别随机生成
    sex = (Player::Sex)QRandomGenerator::global()->bounded(2);//范围0,1
    m_robotLeft->setSex(sex);
    sex = (Player::Sex)QRandomGenerator::global()->bounded(2);//范围0,1
    m_robotRight->setSex(sex);
    sex = (Player::Sex)QRandomGenerator::global()->bounded(2);//范围0,1
    m_user->setSex(sex);

    //玩家/机器人A/机器人B设置上下家
    m_user->setPrevPlayer(m_robotLeft);
    m_user->setNextPlayer(m_robotRight);
    m_robotLeft->setPrevPlayer(m_robotRight);
    m_robotLeft->setNextPlayer(m_user);
    m_robotRight->setPrevPlayer(m_user);
    m_robotRight->setNextPlayer(m_robotLeft);

    //指定当前玩家
    m_currPlayer = m_user;

    // 连接玩家下注抢地主的信号和槽函数
    connect(m_user,&UserPlayer::notifyGrabLordBet,this,&GameControl::onGrabBet);
    connect(m_robotLeft,&Robot::notifyGrabLordBet,this,&GameControl::onGrabBet);
    connect(m_robotRight,&Robot::notifyGrabLordBet,this,&GameControl::onGrabBet);
    //连接出牌玩家对象信号
    connect(this,&GameControl::pendingInfo, m_robotLeft,&Robot::storePendingInfo);
    connect(this,&GameControl::pendingInfo, m_robotRight,&Robot::storePendingInfo);
    connect(this,&GameControl::pendingInfo, m_user,&UserPlayer::storePendingInfo);
    //处理玩家出牌
    connect(m_user,&UserPlayer::notifyPlayHand,this,&GameControl::onPlayHand);
    connect(m_robotLeft,&Robot::notifyPlayHand,this,&GameControl::onPlayHand);
    connect(m_robotRight,&Robot::notifyPlayHand,this,&GameControl::onPlayHand);
}

Robot *GameControl::leftRobot()
{
    return m_robotLeft;
}

Robot *GameControl::rightRobot()
{
    return m_robotRight;
}

UserPlayer *GameControl::userPlayer()
{
    return m_user;
}

void GameControl::setCurrentPlayer(Player *player)
{
    m_currPlayer = player;
}

Player *GameControl::currentPlayer()
{
    return m_currPlayer;
}

Player *GameControl::pendPlayer()
{
    return m_pendPlayer;
}

Cards GameControl::pendCards()
{
    return m_pendCards;
}

void GameControl::allCardsInit()
{
    m_allCards.clear();
    //避开大小王进行创建牌
    for(int p = Card::Card_Begin+1; p<Card::Card_SJ; p++){
        for(int s = Card::Suit_Begin+1; s<Card::Suit_End; s++){
            Card c((Card::CardPoint)p,(Card::CardSuit)s);
            m_allCards.add(c);
        }
    }
    //初始化大小王
    m_allCards.add(Card(Card::Card_SJ, Card::Suit_Begin));
    m_allCards.add(Card(Card::Card_BJ,Card::Suit_Begin));
}

Card GameControl::takeOneCard()
{
    return m_allCards.takeRandCard();
}

Cards GameControl::surPlusCards()
{
    //发到最后只剩下3张了
    return m_allCards;
}

void GameControl::resetCardData()
{
    //洗牌
    allCardsInit();
    //清空所有玩家手里的牌
    m_user->clearCards();
    m_robotLeft->clearCards();
    m_robotRight->clearCards();
    //初始化出牌玩家和打出的牌
    m_pendPlayer = nullptr;
    m_pendCards.clear();
}

void GameControl::startLordCard()
{
    m_currPlayer->prepareCallLord();//调用准备叫地主函数
    emit playerStatusChange(m_currPlayer, ThinkingForCallLord);
}

void GameControl::becomeLord(Player* player, int bet)
{
    m_curBet = bet;
    //设置每个玩家的角色（地主、农民）
    player->setRole(Player::Lord);
    player->prevPlayer()->setRole(Player::Farmer);
    player->nextPlayer()->setRole(Player::Farmer);
    m_currPlayer = player;//地主就是当前玩家
    player->storeDispatchCard(m_allCards);//地主收回三张地主牌
    //定时器，成为地主后延迟1秒再出牌，目的是假装一个思考的时间
    QTimer::singleShot(1000, this, [=](){
        emit gameStatusChanged(PlayingHand);
        emit playerStatusChange(player, ThinkingForPlayHand);
        m_currPlayer->preparePlayHand();//调用准备出牌函数
    });
}

int GameControl::playerMaxBet()
{
    return m_betRecord.bet;
}

void GameControl::onGrabBet(Player *player, int bet)
{
    // 通知主界面，玩家叫地主（提示更新信息显示）
    if(bet == 0 || m_betRecord.bet >= bet){
        //说明当前玩家下的注比前面的小（无效）
        emit notifyGradLordBet(player, 0, false);

    }else if(bet > 0 && m_betRecord.bet == 0){
        //说明这个玩家是第一个抢地主的人
        emit notifyGradLordBet(player, bet, true);

    }else{
        //说明这个玩家不是第一个抢地主的人
        emit notifyGradLordBet(player, bet, false);

    }
    // 判断玩家是否下注3分，是则直接结束
    if(bet == 3){
        //当前玩家直接变成地主
        becomeLord(player, bet);
        //清空下注的所有信息
        m_betRecord.reset();
        return;
    }
    //下注不够3分，对玩家的分数进行比较，分数高的是地主
    if(m_betRecord.bet < bet){
        m_betRecord.bet = bet;
        m_betRecord.player = player;
    }
    m_betRecord.times++;
    if(m_betRecord.times == 3){
        if(m_betRecord.bet == 0){//大家都不抢地主
            //给主窗口发一个信号重新发牌
            emit gameStatusChanged(DispatchCard);

        }else{
            becomeLord(m_betRecord.player,m_betRecord.bet);

        }
        m_betRecord.reset();
        return;
    }
    // 切换玩家，通知下一个玩家继续抢地主
    m_currPlayer = player->nextPlayer();
    //发送信号给主界面，告知当前状态还是抢地主
    emit playerStatusChange(m_currPlayer, ThinkingForCallLord);
    m_currPlayer->prepareCallLord();
}

void GameControl::onPlayHand(Player *player, Cards& cards)
{
    // 1.将玩家出牌的信号转发给主界面
    emit notifyPlayHand(player, cards);
    // 2.判断玩家出的牌是不是空牌,不是则给其他玩家发送信号，保存出牌玩家打出的牌
    if(!cards.isEmpty()){
        m_pendPlayer = player;
        m_pendCards = cards;
        emit pendingInfo(player,cards);
    }
    //如果有炸弹，底分翻倍
    PlayHand::HandType type = PlayHand(cards).handType();
    if(type == PlayHand::Hand_Bomb || type == PlayHand::Hand_Bomb_Jokers){
        m_curBet *= 2;
    }
    // 3.如果玩家出完了，计算本局游戏的总得分
    if(player->cards().isEmpty()){
        Player* prev = player->prevPlayer();
        Player* next = player->nextPlayer();
        if(player->role() == Player::Lord){
            player->setScore(player->score() + 2*m_curBet);
            prev->setScore(prev->score() - m_curBet);
            next->setScore(next->score() - m_curBet);
            player->setIsWin(true);
            prev->setIsWin(false);
            next->setIsWin(false);
        }else{
            player->setScore(player->score() + m_curBet);
            player->setIsWin(true);
            if(prev->role() == Player::Lord){
                prev->setScore(prev->score() - 2*m_curBet);
                prev->setIsWin(false);
                next->setScore(next->score() + m_curBet);
                next->setIsWin(true);

            }else{
                prev->setScore(prev->score() + m_curBet);
                prev->setIsWin(true);
                next->setScore(next->score() - 2*m_curBet);
                next->setIsWin(false);
            }
        }
        emit playerStatusChange(player, GameControl::Winning);
        return;
    }
    // 4.通知下一个玩家继续出牌
    m_currPlayer = player->nextPlayer();
    m_currPlayer->preparePlayHand();
    emit playerStatusChange(m_currPlayer, GameControl::ThinkingForPlayHand);
}

void GameControl::clearPlayerScore()
{
    m_user->setScore(0);
    m_robotLeft->setScore(0);
    m_robotRight->setScore(0);
}
